package com.awenhui.demo.core.utils;

import cn.hutool.core.codec.Base64Encoder;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 二维码帮助类
 *
 * @author yuxf
 * @version 1.0
 * @date 2020/8/4 12:03
 */
public class QrCodeUtils {
    public static BufferedImage qrCode(String content, int qrCodeSize) throws WriterException, IOException {
        //设置二维码属性
        Hashtable<EncodeHintType, Object> hintMap = new Hashtable<>();
        hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);  // 矫错级别,级别越高越容易被识别
        hintMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //创建比特矩阵(位矩阵)的QR码编码的字符串
        BitMatrix byteMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);
        BufferedImage bufferedImage = writeToBufferedImage(byteMatrix);
        return bufferedImage;

    }

    /**
     * 二维码保存在文件中
     */
    public static BufferedImage writeToBufferedImage(BitMatrix bitMatrix) throws IOException {
        //// 也可以使用zxing扩展类库提供的方法
        // BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                image.setRGB(i, j, bitMatrix.get(i, j) ? 0XFF000000 : 0XFFFFFF);
            }
        }
        return image;
    }

    /**
     * 将二维码写入文件
     *
     * @param path
     */
    public static void writeToFile(String path, BufferedImage image) throws IOException {
        ImageIO.write(image, "png", new FileOutputStream(path));
    }

    /**
     * 二维码去掉白边
     *
     * @param matrix ${@link BitMatrix}
     * @return BitMatrix ${@link BitMatrix}
     * @author zhouxuanhong
     * @date 2019-11-12 15:09
     */
    private static BitMatrix deleteWhite(BitMatrix matrix) {
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2] + 1;
        int resHeight = rec[3] + 1;
        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = 0; i < resWidth; i++) {
            for (int j = 0; j < resHeight; j++) {
                if (matrix.get(i + rec[0], j + rec[1])) {
                    resMatrix.set(i, j);
                }
            }
        }
        return resMatrix;
    }


    /**
     * 写入http响应
     */
    public static void writeToBase64(HttpServletResponse response, BufferedImage image) throws IOException {
        response.setContentType("image/png");
        ImageIO.write(image, "png", response.getOutputStream());
    }

    /**
     * 写入http响应
     */
    public static void writeToResponse(HttpServletResponse response, BufferedImage image) throws IOException {
        response.setContentType("image/png");
        ImageIO.write(image, "png", response.getOutputStream());
    }

    /**
     * 获取base64二维码
     *
     * @param contents
     * @param width
     * @return
     */
    public static String writeToBase64(String contents, int width) throws IOException, WriterException {

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        BufferedImage bufferedImage = qrCode(contents, width);
        ImageIO.write(bufferedImage, "png", out);
        byte[] bytes = out.toByteArray();
        String base64 = Base64Encoder.encode(bytes);
        return base64;
    }


    /**
     * 识别二维码
     *
     * @param inputStream ${@link InputStream} 待识别图片
     * @return
     * @author yuxf
     * @date 2019-09-27 10:56
     */
    public static String checkoutQrCode(InputStream inputStream) throws IOException, NotFoundException {
        BufferedImage image = ImageIO.read(inputStream);
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Map<DecodeHintType, Object> hints = new LinkedHashMap<>();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        Result result = null;
        result = new MultiFormatReader().decode(bitmap, hints);
        String text = result.getText();

        return text;
    }


    /**
     * 识别二维码
     *
     * @param imageUrl ${@link String} 图片地址
     * @return 识别结果
     * @author zhouxuanhong
     * @date 2019-09-27 10:56
     */
    public static String checkoutQrCode(String imageUrl)
            throws Exception {
        HttpURLConnection connection = (HttpURLConnection) new URL(imageUrl)
                .openConnection();
        connection.setReadTimeout(5000);
        connection.setConnectTimeout(5000);
        connection.setRequestMethod("GET");
        InputStream inputStream = null;
        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            inputStream = connection.getInputStream();
        } else {
            if (inputStream != null) {
                inputStream.close();
            }
            throw new Exception("二维码不存在," + connection.getResponseCode());
        }
        return checkoutQrCode(inputStream);
    }
}
